<template>
    <div style="overflow: hidden">
        <Alert v-if="!readOnly">
            <Row type="flex" justify="end">
                <Col span="18">
                    规则{{ruleName}}维护,表达式展示语言
                    <i-switch size="large" v-model="chineseLang">
                        <span slot="open">中文</span>
                        <span slot="close">程序</span>
                    </i-switch>
                </Col>
                <Col span="6" >
                    <div style="float: right">
                        <Button type="error" @click="reloadRule" icon="ios-refresh-circle">重置</Button>
                        <Button type="success" @click="checkRule" icon="ios-checkmark-circle">校验</Button>
                        <Button type="info" :loading="saving" @click="saveRule" icon="md-browsers">保存</Button>
                    </div>
                </Col>
            </Row>
            <template slot="desc">
                {{expressValue}}
            </template>
        </Alert>
        <Alert v-else>
            <Row type="flex" justify="start">
                <Col span="18">
                    规则{{ruleName}},表达式展示语言
                    <i-switch size="large" v-model="chineseLang">
                        <span slot="open">中文</span>
                        <span slot="close">程序</span>
                    </i-switch>
                </Col>
            </Row>
            <template slot="desc">
                {{expressValue}}
            </template>
        </Alert>
        <div v-show="!readOnly">
            <scrollBar :showAll="true" :width="width" :height="height" ref="scrollBar" v-if="width>0&&height>0">
                <rule-tree :style="calRuleStyle"  v-if="init" @calexp="setExpressValue"  :chineseLang="chineseLang" :treeData="ruleTree" :depth="depth" :ruleAtoms="ruleAtoms" :operations="operations"  />
            </scrollBar>
            <div v-else>
                <rule-tree  v-if="init" @calexp="setExpressValue"  :chineseLang="chineseLang" :treeData="ruleTree" :depth="depth" :ruleAtoms="ruleAtoms" :operations="operations"  />
            </div>
        </div>
        <Spin size="large" fix v-if="!init"></Spin>
    </div>
</template>
<script>
    import ruleTree from './component/rule-tree'
    import {getByTypes} from "_p/basic/api/admin/datadic";
    import {deepClone} from "@/libs/utils/ObjectClone";
    import axios from '@/libs/request/axios'
    import {saveRule,checkRule} from '_p/basic/api/rule/rule'
    import Constants from "_c/rui-auto/rui-rules/src/component/constant/constant";
    import {getUri} from "@/libs/tools";
    import scrollBar from "./component/rule-scroller-bars";
   const findComponentDownwardByTagName = function (context,tagName){
        const childrens = context.$children;
        let children = [];
        if (childrens.length) {
            for (const child of childrens) {
                const name = child.$options._componentTag;
                if (name === tagName) {
                    children.push(child);
                }
                children.push(...findComponentDownwardByTagName(child, tagName));
            }
        }
        return children;
    }
    export default {
        name:'rui-rules',
        components: {
            'ruleTree':ruleTree,
            'scrollBar':scrollBar,
        },
        props: {
            ruleAtoms: {
                type: Array,
                default: function () {
                    return []
                },
                require:true
            },
            ruleName:{
                type:String,
                require:true
            },
            ruleId:{
                type:String,
                require:false,
                default:()=>{return ''}
            },
            ruleGroup:{
                type:String,
                require:true
            },
            businessScenario:{
                type:String,
                require:true
            },
            ruleData: {
                type: Array,
                default: function () {
                    return []
                },
            },
            ruleOut:{
                type:String,
                require:false
            },
            sortOrder:{
                type:Number,
                default: function () {
                    return 0
                },
            },
            activeStartDate:{
                type:String,
                default: function () {
                    return '19700101000000'
                }
            },
            activeEndDate:{
                type:String,
                default: function () {
                    return '20991231235959'
                }
            },
            initDate:{
                type:Boolean,
                default: function () {
                    return false
                }
            },
            width:{
                type: Number,
                default: function () {
                    return -1
                },
            },
            height:{
                type: Number,
                default: function () {
                    return -1
                },
            },
            readOnly:{
                type:Boolean,
                default(){
                    return false;
                }
            }
        },

        data() {
            return {
                operations:[],
                ruleTree:[],
                depth:0,
                saving:false,
                hasIfNode:false,
                dicKeys: [],
                dataDic: {},
                custDicKeys:[],
                custDics:{},
                custDicFun:{},
                cascaderKeys:[],
                cascaderFirstLevelData:{},
                cascaderFun:{},
                init:false,
                chineseLang: false,
                expressValue:'',
                dbId:'',
                ruleValidate:true,
                saved:false,
                requestPath:'',
                treeMaxWidth:400
            }
        },
        provide () {
            return {
                RuiRule: this
            };
        },
        created() {
            if(this.$route.meta.params&&this.$route.meta.params.requestPath&&this.$route.meta.params.requestPath!==''){
                this.requestPath = this.$route.meta.params.requestPath;
            }else{
                this.requestPath = getUri('rule');
            }
            this.dbId = this.ruleId;
            this.operations.push(...deepClone(Constants.operators.compareOperator));
            this.operations.push(...deepClone(Constants.operators.specialCompare));
            let self = this;
            self.checkHasIfNode();
            self.ruleTree.push({
                label:self.ruleName,
                id:self.ruleId,
                rows:deepClone(self.ruleData)
            });
            self.ruleAtoms.forEach(atom => {

                if(atom.component=='dic') {
                    if (!atom.componentConfig.dicKey || atom.componentConfig.dicKey === '') {
                        this.$Message.error("原子" + atom.name + "配置错误(没有配置字典key)")
                    }
                }else if(atom.component=='custDic'){
                    if (!atom.componentConfig.dicUrl || atom.componentConfig.dicUrl === '') {
                        this.$Message.error("原子" + atom.name + "配置错误(没有配置自定义字典地址)")
                    }
                }else if(atom.component=='cascader'){
                    if (!atom.componentConfig.level || !atom.componentConfig.levelConfig||atom.componentConfig.level!=atom.componentConfig.levelConfig.length) {
                        this.$Message.error("原子" + atom.name + "级联数据获取地址配置错误")
                    }
                }
                if(atom.component=='dic'&&atom.componentConfig.dicKey&&!self.dicKeys.includes(atom.componentConfig.dicKey)) {
                    self.dicKeys.push(atom.componentConfig.dicKey);
                }

                if(atom.component=='custDic'&&atom.componentConfig.dicUrl&&!self.custDicKeys.includes(atom.key)) {
                    self.custDicKeys.push(atom.key);
                    let requestObject={
                        url: atom.componentConfig.dicUrl,
                        method:atom.componentConfig.method,
                    };
                    if(atom.componentConfig.method=='get'&&atom.componentConfig.params!=''){
                        requestObject.params = JSON.parse(atom.componentConfig.params)
                    }else if(atom.componentConfig.method=='post'&&atom.componentConfig.params!=''){
                        requestObject.data = JSON.parse(atom.componentConfig.params)
                    }
                    self.custDicFun[atom.key]=()=>{
                        return axios.request(requestObject);
                    }
                }
                if(atom.component=='cascader'&&atom.componentConfig.level==atom.componentConfig.levelConfig.length&&!self.cascaderKeys.includes(atom.key)){
                    self.cascaderKeys.push(atom.key);
                    self.cascaderFun[atom.key] = (url,method,param,superKey,superValue)=>{
                        let requestObject={
                            url: url,
                            method:method,
                        };
                        let paramObj;
                        if(param!=''){
                            paramObj = JSON.parse(param)
                        }else{
                            paramObj = {};
                        }
                        if(superKey!=''&&superValue!=''){
                            paramObj[superKey] = superValue;
                        }
                        if(method=='get'){
                            requestObject.params = paramObj
                        }else if(method=='post'){
                            requestObject.data = paramObj
                        }
                        return axios.request(requestObject)
                    };
                }
            });
            this.initDataDic();
        },

        watch: {
            ruleName(){
                if(this.ruleTree.length>0){
                    this.ruleTree[0].label=this.ruleName;
                }
            }
        },
        computed:{
            calRuleStyle(){
                if(this.width<0){
                    return {width:'auto'}
                }
                return {width: this.treeMaxWidth+'px'}
            }
        },
        methods: {
            validateRule(){
                const items = findComponentDownwardByTagName(this, 'tree-item');
                this.ruleValidate = items.filter(value => !value.itemValidate&&!value.isFolder).length===0
            },
            findMaxWidth(){
                if(this.$refs.scrollBar){
                    let max=0;
                    let list = this.$refs.scrollBar.$el.getElementsByClassName("expressWidthCal");
                    for (let index = 0; index < list.length; index++) {
                        if(list[index].getBoundingClientRect().width>max){
                            max = list[index].getBoundingClientRect().width;
                        }
                    }
                    return max==0?this.width:(max+400);
                }
                return this.width;
            },
            findAtomByKey(key){
               let findAtom = null;
               this.ruleAtoms.forEach(atom=>{
                   if(atom.key===key){
                       findAtom = atom;
                   }
               })
                return findAtom
            },
            initCustDic: async function (key){
                return await (this.custDicFun[key])()
            },
            initCascaderFirstLevel: async function (key){
                let atom = this.findAtomByKey(key);
                let config = atom.componentConfig.levelConfig[0];
                return await (this.cascaderFun[key])(config.url,config.method,config.params,'','')
            },
            initDataDic:async function (){
                for(let i=0;i<this.custDicKeys.length;i++){
                    this.custDics[this.custDicKeys[i]] = []
                   let rtns =   await this.initCustDic(this.custDicKeys[i])
                    if(rtns.code=='0000'){
                        rtns.data.forEach(dic=>{
                            this.custDics[this.custDicKeys[i]].push({
                                title:dic.title,
                                value:dic.value
                            })
                        })
                    }else{
                        this.$Message.error('自定义数据字典'+this.custDicKeys[i]+'加载失败请检查配置');
                    }
                }
                for(let i=0;i<this.cascaderKeys.length;i++){
                    this.cascaderFirstLevelData[this.cascaderKeys[i]] = []
                    let rtns =   await this.initCascaderFirstLevel(this.cascaderKeys[i])
                    if(rtns.code=='0000'){
                        rtns.data.forEach(val=>{
                            this.cascaderFirstLevelData[this.cascaderKeys[i]].push({
                                label:val.title,
                                value:val.value,
                                children:[],
                                _level:0,
                                loading:false
                            })
                        })
                    }else{
                        this.$Message.error('级联参数'+this.custDicKeys[i]+'加载失败请检查配置');
                    }
                }
                let self = this;
                if(this.dicKeys.length>0) {
                    getByTypes(this.dicKeys).then(res => {
                        if (res.code === "0000" && res.data) {
                            self.dataDic = res.data;
                            self.init = true;
                            self.$nextTick(()=>{
                                self.chineseLang = true;
                            });
                        }
                    });
                }else{
                    self.init = true;
                    self.$nextTick(()=>{
                        self.chineseLang = true;
                    });
                }
            },
            checkHasIfNode(){
                let self = this;
                this.ruleData.forEach(ruleRow=>{
                    if(ruleRow.type==='choice'){
                        self.hasIfNode = true;
                    }
                })
            },
            setExpressValue(expressValue){
                this.expressValue = expressValue;
                if(this.$refs.scrollBar) {
                    this.$refs.scrollBar.resize();
                }
                this.treeMaxWidth = this.findMaxWidth();
            },
            checkRule(){
                this.validateRule();
                if(!this.ruleTree[0].rows||this.ruleTree[0].rows.length==0){
                    this.$Message.error("规则内容为空");
                    return;
                }
                if(!this.ruleValidate){
                    this.$Message.error("规则配置不正确");
                    return;
                }
                let ruleInfo={
                    id:this.dbId,
                    ruleNo:this.businessScenario,
                    ruleName:this.ruleName,
                    ruleGroup:this.ruleGroup,
                    ruleData:JSON.stringify(this.ruleTree[0].rows)
                }
                checkRule(ruleInfo,this.requestPath).then((res)=>{
                    if(res.code=='0000'&&res.data.validate){
                        this.$Message.success("规则校验成功");
                    }else{
                        this.$Message.error("规则校验失败");
                    }
                }).catch(()=>{

                })
            },
            saveRule(){
                this.validateRule();
                if(!this.ruleTree[0].rows||this.ruleTree[0].rows.length==0){
                    this.$Message.error("规则内容为空");
                    return;
                }
                if(!this.ruleValidate){
                    this.$Message.error("规则配置不正确");
                    return;
                }
                let ruleInfo={
                    id:this.dbId,
                    ruleNo:this.businessScenario,
                    ruleName:this.ruleName,
                    ruleGroup:this.ruleGroup,
                    ruleOut:this.ruleOut,
                    sortOrder:this.sortOrder,
                    ruleData:JSON.stringify(this.ruleTree[0].rows)
                }
                if(this.initDate){
                    ruleInfo.activeEndDate=this.activeEndDate;
                    ruleInfo.activeStartDate=this.activeStartDate;
                }
                this.saving = true;
                saveRule(ruleInfo,this.requestPath).then((res)=>{
                    this.saving = false;
                    if(res.code=='0000'){
                        this.dbId = res.data.id;
                        this.$Message.success("规则保存成功");
                        this.$emit("saved",this.dbId,this.expressValue);
                        this.saved = true;
                    }
                }).catch(()=>{
                    this.saving = false;
                })
            },
            reloadRule(){
                let self = this;
                this.$Modal.confirm({
                    title: "确认",
                    content: '确认重置规则数据?',
                    onOk: () => {
                        if(self.saved) return
                        self.ruleTree.splice(0,1,{
                            label:self.ruleName,
                            id:self.ruleId,
                            rows:deepClone(self.ruleData)
                        });
                        self.saved = false;
                    }
                });
            }
        }
    }
</script>
